//! # 限流算法实现
//!
//! 提供多种限流算法的具体实现，包括令牌桶、漏桶、固定窗口和滑动窗口算法。
//!
//! ## 算法特性
//!
//! * **令牌桶算法** - 允许突发流量，平滑限流
//! * **漏桶算法** - 严格控制流量速度，不允许突发
//! * **固定窗口算法** - 简单高效，但存在边界问题
//! * **滑动窗口算法** - 更平滑的限流效果，内存开销较大
//! * **滑动日志算法** - 最精确的限流，但内存开销最大

use super::{RateLimitAlgorithm, RateLimitConfig, RateLimitDecision, RateLimitStorage, 
           RateLimitResult, RateLimitError, RateLimitAlgorithmType};
use async_trait::async_trait;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tracing::{debug, warn};

/// 令牌桶算法
///
/// 允许突发流量，但长期速率受限。令牌以固定速率添加到桶中，
/// 请求消耗令牌，当桶为空时请求被拒绝。
pub struct TokenBucketAlgorithm {
    storage: Arc<dyn RateLimitStorage>,
}

impl TokenBucketAlgorithm {
    /// 创建新的令牌桶算法
    pub fn new(storage: Arc<dyn RateLimitStorage>) -> Self {
        Self { storage }
    }

    /// 计算需要添加的令牌数
    fn calculate_tokens_to_add(
        last_refill: SystemTime,
        refill_rate: u32,
        max_capacity: u32,
        current_tokens: u32,
    ) -> u32 {
        let now = SystemTime::now();
        let time_elapsed = now.duration_since(last_refill).unwrap_or(Duration::ZERO);
        
        // 计算应该添加的令牌数
        let tokens_to_add = (time_elapsed.as_secs_f64() * refill_rate as f64) as u32;
        
        // 不能超过桶的最大容量
        std::cmp::min(tokens_to_add, max_capacity.saturating_sub(current_tokens))
    }

    /// 获取令牌桶状态
    async fn get_bucket_state(&self, key: &str) -> RateLimitResult<(u32, SystemTime)> {
        // 尝试获取当前令牌数和最后补充时间
        let tokens_key = format!("{}:tokens", key);
        let time_key = format!("{}:last_refill", key);
        
        let current_tokens = self.storage.get_counter(&tokens_key).await.unwrap_or(0) as u32;
        
        // 获取最后补充时间（存储为Unix时间戳）
        let last_refill_timestamp = self.storage.get_counter(&time_key).await.unwrap_or(0);
        let last_refill = if last_refill_timestamp > 0 {
            UNIX_EPOCH + Duration::from_secs(last_refill_timestamp)
        } else {
            // 返回一个明确的"未初始化"时间，使用UNIX_EPOCH
            UNIX_EPOCH
        };
        
        Ok((current_tokens, last_refill))
    }

    /// 更新令牌桶状态
    async fn update_bucket_state(
        &self,
        key: &str,
        tokens: u32,
        config: &RateLimitConfig,
    ) -> RateLimitResult<()> {
        let tokens_key = format!("{}:tokens", key);
        let time_key = format!("{}:last_refill", key);
        
        let now = SystemTime::now();
        let timestamp = now.duration_since(UNIX_EPOCH).unwrap().as_secs();
        
        // 设置令牌数和最后补充时间
        self.storage.set_counter(&tokens_key, tokens as u64, config.window_duration).await?;
        self.storage.set_counter(&time_key, timestamp, config.window_duration).await?;
        
        Ok(())
    }
}

#[async_trait]
impl RateLimitAlgorithm for TokenBucketAlgorithm {
    async fn is_allowed(
        &self,
        key: &str,
        tokens_requested: u32,
        config: &RateLimitConfig,
    ) -> RateLimitResult<RateLimitDecision> {
        let refill_rate = config.refill_rate.unwrap_or(config.max_requests);
        let max_capacity = config.burst_capacity.unwrap_or(config.max_requests);
        
        debug!("Token bucket check for key: {}, tokens requested: {}, refill rate: {}, capacity: {}", 
               key, tokens_requested, refill_rate, max_capacity);

        // 获取当前桶状态
        let (mut current_tokens, last_refill) = self.get_bucket_state(key).await?;
        
        // 检查是否为首次请求（令牌数为0且时间戳为UNIX_EPOCH）
        let is_first_request = current_tokens == 0 && last_refill == UNIX_EPOCH;
        
        if is_first_request {
            // 首次请求，初始化桶为满状态
            current_tokens = max_capacity;
            // 更新初始状态
            self.update_bucket_state(key, current_tokens, config).await?;
        } else {
            // 计算需要添加的令牌
            let tokens_to_add = Self::calculate_tokens_to_add(
                last_refill,
                refill_rate,
                max_capacity,
                current_tokens,
            );
            
            // 更新当前令牌数
            current_tokens = std::cmp::min(current_tokens + tokens_to_add, max_capacity);
        }
        
        // 检查是否有足够的令牌
        if current_tokens >= tokens_requested {
            // 消耗令牌
            current_tokens -= tokens_requested;
            
            // 更新状态
            self.update_bucket_state(key, current_tokens, config).await?;
            
            let reset_time = SystemTime::now() + Duration::from_secs(
                (max_capacity.saturating_sub(current_tokens)) as u64 / refill_rate.max(1) as u64
            );
            
            Ok(RateLimitDecision::allowed(current_tokens, reset_time))
        } else {
            // 令牌不足，计算重置时间
            let tokens_needed = tokens_requested - current_tokens;
            let reset_time = SystemTime::now() + Duration::from_secs(
                tokens_needed as u64 / refill_rate.max(1) as u64
            );
            
            // 更新状态（不消耗令牌）
            self.update_bucket_state(key, current_tokens, config).await?;
            
            Ok(RateLimitDecision::rejected(
                format!("Token bucket empty, need {} tokens, have {}", tokens_requested, current_tokens),
                reset_time,
            ))
        }
    }

    async fn get_remaining(&self, key: &str, config: &RateLimitConfig) -> RateLimitResult<u32> {
        let (mut current_tokens, last_refill) = self.get_bucket_state(key).await?;
        let refill_rate = config.refill_rate.unwrap_or(config.max_requests);
        let max_capacity = config.burst_capacity.unwrap_or(config.max_requests);
        
        // 检查是否为首次请求
        let is_first_request = current_tokens == 0 && last_refill == UNIX_EPOCH;
        
        if is_first_request {
            // 首次请求，返回满桶容量
            return Ok(max_capacity);
        }
        
        // 计算当前应该有的令牌数（包括补充的令牌）
        let tokens_to_add = Self::calculate_tokens_to_add(
            last_refill,
            refill_rate,
            max_capacity,
            current_tokens,
        );
        
        let total_tokens = std::cmp::min(current_tokens + tokens_to_add, max_capacity);
        
        // 注意：get_remaining不应该修改状态，只返回计算结果
        Ok(total_tokens)
    }

    async fn reset(&self, key: &str) -> RateLimitResult<()> {
        let tokens_key = format!("{}:tokens", key);
        let time_key = format!("{}:last_refill", key);
        
        self.storage.delete_counter(&tokens_key).await?;
        self.storage.delete_counter(&time_key).await?;
        
        Ok(())
    }

    fn get_algorithm_type(&self) -> RateLimitAlgorithmType {
        RateLimitAlgorithmType::TokenBucket
    }

    fn get_algorithm_name(&self) -> &str {
        "token_bucket"
    }
}

/// 漏桶算法
///
/// 以固定速率处理请求，不允许突发流量。请求进入队列，
/// 以固定速率从队列中取出处理。
pub struct LeakyBucketAlgorithm {
    storage: Arc<dyn RateLimitStorage>,
}

impl LeakyBucketAlgorithm {
    /// 创建新的漏桶算法
    pub fn new(storage: Arc<dyn RateLimitStorage>) -> Self {
        Self { storage }
    }

    /// 计算漏掉的请求数
    fn calculate_leaked_requests(
        last_leak: SystemTime,
        leak_rate: u32,
    ) -> u32 {
        let now = SystemTime::now();
        let time_elapsed = now.duration_since(last_leak).unwrap_or(Duration::ZERO);
        
        // 计算在这段时间内应该漏掉的请求数
        (time_elapsed.as_secs_f64() * leak_rate as f64) as u32
    }

    /// 获取漏桶状态
    async fn get_bucket_state(&self, key: &str) -> RateLimitResult<(u32, SystemTime)> {
        let requests_key = format!("{}:requests", key);
        let time_key = format!("{}:last_leak", key);
        
        let current_requests = self.storage.get_counter(&requests_key).await.unwrap_or(0) as u32;
        
        let last_leak_timestamp = self.storage.get_counter(&time_key).await.unwrap_or(0);
        let last_leak = if last_leak_timestamp > 0 {
            UNIX_EPOCH + Duration::from_secs(last_leak_timestamp)
        } else {
            SystemTime::now()
        };
        
        Ok((current_requests, last_leak))
    }

    /// 更新漏桶状态
    async fn update_bucket_state(
        &self,
        key: &str,
        requests: u32,
        config: &RateLimitConfig,
    ) -> RateLimitResult<()> {
        let requests_key = format!("{}:requests", key);
        let time_key = format!("{}:last_leak", key);
        
        let now = SystemTime::now();
        let timestamp = now.duration_since(UNIX_EPOCH).unwrap().as_secs();
        
        self.storage.set_counter(&requests_key, requests as u64, config.window_duration).await?;
        self.storage.set_counter(&time_key, timestamp, config.window_duration).await?;
        
        Ok(())
    }
}

#[async_trait]
impl RateLimitAlgorithm for LeakyBucketAlgorithm {
    async fn is_allowed(
        &self,
        key: &str,
        _tokens_requested: u32,
        config: &RateLimitConfig,
    ) -> RateLimitResult<RateLimitDecision> {
        let leak_rate = config.refill_rate.unwrap_or(config.max_requests);
        let bucket_capacity = config.burst_capacity.unwrap_or(config.max_requests);
        
        debug!("Leaky bucket check for key: {}, leak rate: {}, capacity: {}", 
               key, leak_rate, bucket_capacity);

        // 获取当前桶状态
        let (mut current_requests, last_leak) = self.get_bucket_state(key).await?;
        
        // 计算漏掉的请求数
        let leaked_requests = Self::calculate_leaked_requests(last_leak, leak_rate);
        
        // 更新当前请求数
        current_requests = current_requests.saturating_sub(leaked_requests);
        
        // 检查是否可以接受新请求
        if current_requests < bucket_capacity {
            // 接受请求
            current_requests += 1;
            
            // 更新状态
            self.update_bucket_state(key, current_requests, config).await?;
            
            let reset_time = SystemTime::now() + Duration::from_secs(
                current_requests as u64 / leak_rate.max(1) as u64
            );
            
            Ok(RateLimitDecision::allowed(bucket_capacity - current_requests, reset_time))
        } else {
            // 桶已满，计算需要等待的时间
            let wait_time = Duration::from_secs(1) / leak_rate.max(1);
            let reset_time = SystemTime::now() + wait_time;
            
            // 更新状态（不接受请求）
            self.update_bucket_state(key, current_requests, config).await?;
            
            Ok(RateLimitDecision::rejected(
                "Leaky bucket is full".to_string(),
                reset_time,
            ))
        }
    }

    async fn get_remaining(&self, key: &str, config: &RateLimitConfig) -> RateLimitResult<u32> {
        let (current_requests, last_leak) = self.get_bucket_state(key).await?;
        let leak_rate = config.refill_rate.unwrap_or(config.max_requests);
        let bucket_capacity = config.burst_capacity.unwrap_or(config.max_requests);
        
        // 计算当前应该有的请求数
        let leaked_requests = Self::calculate_leaked_requests(last_leak, leak_rate);
        let adjusted_requests = current_requests.saturating_sub(leaked_requests);
        
        Ok(bucket_capacity.saturating_sub(adjusted_requests))
    }

    async fn reset(&self, key: &str) -> RateLimitResult<()> {
        let requests_key = format!("{}:requests", key);
        let time_key = format!("{}:last_leak", key);
        
        self.storage.delete_counter(&requests_key).await?;
        self.storage.delete_counter(&time_key).await?;
        
        Ok(())
    }

    fn get_algorithm_type(&self) -> RateLimitAlgorithmType {
        RateLimitAlgorithmType::LeakyBucket
    }

    fn get_algorithm_name(&self) -> &str {
        "leaky_bucket"
    }
}

/// 固定窗口算法
///
/// 在固定时间窗口内限制请求数量。简单高效，但在窗口边界处
/// 可能出现突发流量问题。
pub struct FixedWindowAlgorithm {
    storage: Arc<dyn RateLimitStorage>,
}

impl FixedWindowAlgorithm {
    /// 创建新的固定窗口算法
    pub fn new(storage: Arc<dyn RateLimitStorage>) -> Self {
        Self { storage }
    }

    /// 获取当前窗口的键
    fn get_window_key(&self, key: &str, window_duration: Duration) -> String {
        let now = SystemTime::now();
        let timestamp = now.duration_since(UNIX_EPOCH).unwrap().as_secs();
        let window_start = (timestamp / window_duration.as_secs()) * window_duration.as_secs();
        
        format!("{}:window:{}", key, window_start)
    }
}

#[async_trait]
impl RateLimitAlgorithm for FixedWindowAlgorithm {
    async fn is_allowed(
        &self,
        key: &str,
        tokens_requested: u32,
        config: &RateLimitConfig,
    ) -> RateLimitResult<RateLimitDecision> {
        debug!("Fixed window check for key: {}, tokens requested: {}, max: {}", 
               key, tokens_requested, config.max_requests);

        let window_key = self.get_window_key(key, config.window_duration);
        
        // 增加计数器
        let current_count = self.storage.increment_counter(
            &window_key,
            tokens_requested as u64,
            config.window_duration,
        ).await?;
        
        // 检查是否超过限制
        if current_count <= config.max_requests as u64 {
            let remaining = config.max_requests.saturating_sub(current_count as u32);
            
            // 计算窗口重置时间
            let now = SystemTime::now();
            let timestamp = now.duration_since(UNIX_EPOCH).unwrap().as_secs();
            let window_start = (timestamp / config.window_duration.as_secs()) * config.window_duration.as_secs();
            let reset_time = UNIX_EPOCH + Duration::from_secs(window_start + config.window_duration.as_secs());
            
            Ok(RateLimitDecision::allowed(remaining, reset_time))
        } else {
            // 超过限制，需要回滚计数器
            let _ = self.storage.increment_counter(
                &window_key,
                -(tokens_requested as i64) as u64, // 这里需要处理负数
                config.window_duration,
            ).await;
            
            // 计算重置时间
            let now = SystemTime::now();
            let timestamp = now.duration_since(UNIX_EPOCH).unwrap().as_secs();
            let window_start = (timestamp / config.window_duration.as_secs()) * config.window_duration.as_secs();
            let reset_time = UNIX_EPOCH + Duration::from_secs(window_start + config.window_duration.as_secs());
            
            Ok(RateLimitDecision::rejected(
                format!("Fixed window limit exceeded: {}/{}", current_count, config.max_requests),
                reset_time,
            ))
        }
    }

    async fn get_remaining(&self, key: &str, config: &RateLimitConfig) -> RateLimitResult<u32> {
        let window_key = self.get_window_key(key, config.window_duration);
        let current_count = self.storage.get_counter(&window_key).await.unwrap_or(0);
        
        Ok(config.max_requests.saturating_sub(current_count as u32))
    }

    async fn reset(&self, key: &str) -> RateLimitResult<()> {
        // 固定窗口算法的重置比较复杂，因为有多个时间窗口
        // 这里只删除当前窗口的数据
        let window_key = self.get_window_key(key, Duration::from_secs(3600)); // 使用默认的1小时窗口
        self.storage.delete_counter(&window_key).await?;
        
        Ok(())
    }

    fn get_algorithm_type(&self) -> RateLimitAlgorithmType {
        RateLimitAlgorithmType::FixedWindow
    }

    fn get_algorithm_name(&self) -> &str {
        "fixed_window"
    }
}

/// 滑动窗口算法
///
/// 使用多个子窗口来实现更平滑的限流效果。比固定窗口算法更精确，
/// 但需要更多的内存和计算资源。
pub struct SlidingWindowAlgorithm {
    storage: Arc<dyn RateLimitStorage>,
    sub_windows: u32,
}

impl SlidingWindowAlgorithm {
    /// 创建新的滑动窗口算法
    pub fn new(storage: Arc<dyn RateLimitStorage>, sub_windows: u32) -> Self {
        Self { 
            storage,
            sub_windows: sub_windows.max(1),
        }
    }

    /// 获取子窗口的键
    fn get_sub_window_keys(&self, key: &str, window_duration: Duration) -> Vec<String> {
        let now = SystemTime::now();
        let timestamp = now.duration_since(UNIX_EPOCH).unwrap().as_secs();
        let sub_window_duration = window_duration.as_secs() / self.sub_windows as u64;
        
        (0..self.sub_windows)
            .map(|i| {
                let window_start = ((timestamp - i as u64 * sub_window_duration) / sub_window_duration) * sub_window_duration;
                format!("{}:sliding:{}:{}", key, window_start, sub_window_duration)
            })
            .collect()
    }
}

#[async_trait]
impl RateLimitAlgorithm for SlidingWindowAlgorithm {
    async fn is_allowed(
        &self,
        key: &str,
        tokens_requested: u32,
        config: &RateLimitConfig,
    ) -> RateLimitResult<RateLimitDecision> {
        debug!("Sliding window check for key: {}, tokens requested: {}, max: {}, sub windows: {}", 
               key, tokens_requested, config.max_requests, self.sub_windows);

        let sub_window_keys = self.get_sub_window_keys(key, config.window_duration);
        let sub_window_duration = config.window_duration / self.sub_windows;
        
        // 获取所有子窗口的计数
        let counts = self.storage.batch_get(&sub_window_keys).await?;
        let total_count = counts.iter().sum::<u64>();
        
        // 检查是否超过限制
        if total_count + tokens_requested as u64 <= config.max_requests as u64 {
            // 只更新当前子窗口
            let current_window_key = &sub_window_keys[0];
            let _ = self.storage.increment_counter(
                current_window_key,
                tokens_requested as u64,
                sub_window_duration,
            ).await?;
            
            let remaining = config.max_requests.saturating_sub((total_count + tokens_requested as u64) as u32);
            let reset_time = SystemTime::now() + sub_window_duration;
            
            Ok(RateLimitDecision::allowed(remaining, reset_time))
        } else {
            let reset_time = SystemTime::now() + sub_window_duration;
            
            Ok(RateLimitDecision::rejected(
                format!("Sliding window limit exceeded: {}/{}", total_count + tokens_requested as u64, config.max_requests),
                reset_time,
            ))
        }
    }

    async fn get_remaining(&self, key: &str, config: &RateLimitConfig) -> RateLimitResult<u32> {
        let sub_window_keys = self.get_sub_window_keys(key, config.window_duration);
        let counts = self.storage.batch_get(&sub_window_keys).await?;
        let total_count = counts.iter().sum::<u64>();
        
        Ok(config.max_requests.saturating_sub(total_count as u32))
    }

    async fn reset(&self, key: &str) -> RateLimitResult<()> {
        let sub_window_keys = self.get_sub_window_keys(key, Duration::from_secs(3600));
        
        for window_key in sub_window_keys {
            let _ = self.storage.delete_counter(&window_key).await;
        }
        
        Ok(())
    }

    fn get_algorithm_type(&self) -> RateLimitAlgorithmType {
        RateLimitAlgorithmType::SlidingWindow
    }

    fn get_algorithm_name(&self) -> &str {
        "sliding_window"
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::rate_limit::storage::MemoryStorage;
    use std::time::Duration;

    #[tokio::test]
    async fn test_token_bucket_algorithm() {
        let storage = Arc::new(MemoryStorage::new());
        let algorithm = TokenBucketAlgorithm::new(storage.clone());

        let config = RateLimitConfig {
            algorithm: RateLimitAlgorithmType::TokenBucket,
            max_requests: 5,
            window_duration: Duration::from_secs(60),
            burst_capacity: Some(5),
            refill_rate: Some(1),
            enabled: true,
            ..Default::default()
        };

        // 前5次请求应该成功（初始令牌桶是满的）
        for i in 0..5 {
            let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
            assert!(decision.allowed, "Request {} should be allowed", i + 1);
            assert_eq!(decision.remaining, 4 - i);
        }

        // 第6次请求应该失败（桶空了）
        let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        assert!(!decision.allowed, "Request 6 should be rejected");
    }

    #[tokio::test]
    async fn test_fixed_window_algorithm() {
        let storage = Arc::new(MemoryStorage::new());
        let algorithm = FixedWindowAlgorithm::new(storage);

        let config = RateLimitConfig {
            algorithm: RateLimitAlgorithmType::FixedWindow,
            max_requests: 5,
            window_duration: Duration::from_secs(60),
            enabled: true,
            ..Default::default()
        };

        // 前5次请求应该成功
        for i in 0..5 {
            let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
            assert!(decision.allowed, "Request {} should be allowed", i + 1);
        }

        // 第6次请求应该失败
        let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        assert!(!decision.allowed, "Request 6 should be rejected");
    }

    #[tokio::test]
    async fn test_leaky_bucket_algorithm() {
        let storage = Arc::new(MemoryStorage::new());
        let algorithm = LeakyBucketAlgorithm::new(storage);

        let config = RateLimitConfig {
            algorithm: RateLimitAlgorithmType::LeakyBucket,
            max_requests: 3, // bucket capacity
            window_duration: Duration::from_secs(60),
            burst_capacity: Some(3),
            refill_rate: Some(1), // 1 request per second leak rate
            enabled: true,
            ..Default::default()
        };

        // 前3次请求应该成功（填满桶）
        for i in 0..3 {
            let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
            assert!(decision.allowed);
            assert_eq!(decision.remaining, 2 - i);
        }

        // 第4次请求应该失败（桶满了）
        let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        assert!(!decision.allowed);
    }

    #[tokio::test]
    async fn test_sliding_window_algorithm() {
        let storage = Arc::new(MemoryStorage::new());
        let algorithm = SlidingWindowAlgorithm::new(storage, 4); // 4 sub-windows

        let config = RateLimitConfig {
            algorithm: RateLimitAlgorithmType::SlidingWindow,
            max_requests: 10,
            window_duration: Duration::from_secs(60),
            enabled: true,
            ..Default::default()
        };

        // 前10次请求应该成功
        for i in 0..10 {
            let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
            assert!(decision.allowed);
            assert_eq!(decision.remaining, 9 - i);
        }

        // 第11次请求应该失败
        let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        assert!(!decision.allowed);
    }

    #[tokio::test]
    async fn test_algorithm_reset() {
        let storage = Arc::new(MemoryStorage::new());
        let algorithm = TokenBucketAlgorithm::new(storage.clone());

        let config = RateLimitConfig {
            max_requests: 2,
            burst_capacity: Some(2),
            refill_rate: Some(1),
            ..Default::default()
        };

        // 消耗所有令牌
        let _ = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        let _ = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        assert!(!decision.allowed, "Should be rejected after consuming all tokens");

        // 重置后应该可以再次请求
        algorithm.reset("test_key").await.unwrap();
        
        // 重置后的第一次请求应该成功（算法会自动初始化为满桶）
        let decision = algorithm.is_allowed("test_key", 1, &config).await.unwrap();
        assert!(decision.allowed, "Should be allowed after reset");
    }

    #[tokio::test]
    async fn test_get_remaining() {
        let storage = Arc::new(MemoryStorage::new());
        let algorithm = FixedWindowAlgorithm::new(storage);

        let config = RateLimitConfig {
            max_requests: 10,
            ..Default::default()
        };

        // 初始应该有10个配额
        let remaining = algorithm.get_remaining("test_key", &config).await.unwrap();
        assert_eq!(remaining, 10);

        // 使用5个配额后应该剩余5个
        let _ = algorithm.is_allowed("test_key", 5, &config).await.unwrap();
        let remaining = algorithm.get_remaining("test_key", &config).await.unwrap();
        assert_eq!(remaining, 5);
    }
}